ConquerMe II: The Lost Princess
by MisterE
Tutorial de Lucifer48 [Immortal Descendants]
(8 ao√t 1999)
Sommaire:
Battle One: One yer Way!
Battle Two: The Tower
The Final Battle: The Princess
Conclusion & Greetings
Battle One: One yer Way!
XXXX:004015E5 CALL USER32!SendDlgItemMessageA ;(WM_GETTEXTLENGTH)
XXXX:004015EA CMP EAX,10 ;le serial comporte-t-il 16 caractΦres ?
... ;(le 16Φme caractΦre n'est pas utilisΘ)
XXXX:00401602 CMP EAX,08
XXXX:00401605 JAE 0040161B ;8 caractΦres minimum pour le nom (sinon ..
... ; .. rajoute des caractΦres nuls pour arriver α 8)
XXXX:0040161B CALL 004012DE ;a explorer!
XXXX:00401620 PUSH 004044A8 ;11111111
XXXX:00401625 PUSH 004044E2 ;encrytion 8 chiffres
XXXX:0040162A CALL KERNEL32!lstrcmp ;comparaison
XXXX:0040162F OR EAX,EAX
Le call 004012DE est composΘ de plusieurs boucles succΘssives. Pour des raisons pratiques,
introduisons les notations suivantes: je dΘsigne X0, X1, X2, ..., Xe
les 15 caractΦres du serial; N0, N1, ..., N7 dΘsignera les caractΦres du nom.
Voilα une premiΦre boucle:
XXXX:00401353 PUSH ECX ;BOUCLE #1 (ecx contient l'indice de boucle)
XXXX:00401354 MOV AL,[ECX+004046E3] ;lit X0, X1, ..., X7
XXXX:0040135A MOV DL,[ECX+00404AE5] ;lit N0, N1, ..., N7
XXXX:00401360 SUB AX,DX
XXXX:00401363 MOV DL,[ECX+00404AF4] ;lit X7, X9, ..., Xe
XXXX:00401369 SUB AX,DX
XXXX:0040136C ADD AX,012C
XXXX:00401370 MOV BL,0A
XXXX:00401372 CWD
XXXX:00401374 IDIV BX
XXXX:00401377 ADD ESI,EDX ;esi va contenir une sorte de checksum
XXXX:00401379 OR DL,30
XXXX:0040137C POP ECX
XXXX:0040137D MOV [ECX+0040449F],DL ;Θcrit le caractΦre final
XXXX:00401383 INC ECX
XXXX:00401384 CMP ECX,08
XXXX:00401387 JNZ 00401353
Cette boucle nous concocte donc un joli petit serial de 8 chiffres (notons le S0, S1, ..., S7).
(X0 - N0 - X7 + 12Ch) mod Ah
+ (X1 - N1 - X8 + 12Ch) mod Ah
+ ...
+ (X7 - N7 - Xe + 12Ch) mod Ah
-------------------------------
= ESI
On continue:
XXXX:004013B2 MOV DL,[004046E3] ;lit X0
XXXX:004013B8 AND DL,0F
XXXX:004013BB ADD ESI,EDX ;valeur dΘfinitive pour esi
XXXX:004013BD XOR EDX,EDX
XXXX:004013BF MOV EAX,ESI
XXXX:004013C1 MOV CL,08
XXXX:004013C3 CWD
XXXX:004013C5 IDIV CX
XXXX:004013C8 XOR ESI,ESI
Le rΘsultat (du modulo) est en EDX, et va influencer la recopie de la chaine X0, X1, ..., X7
de la maniΦre suivante:
XXXX:004013CC MOV AL,[ESI+004046E3] ;lit X0, X1, X2, ..., X7
XXXX:004013D2 MOV [EDX+004044E2],AL ;recopie (dans le dΘsordre)
XXXX:004013D8 INC EDX
XXXX:004013D9 CMP EDX,08
XXXX:004013DC JNZ 004013E3
XXXX:004013DE MOV EDX,00000000
XXXX:004013E3 INC ESI
XXXX:004013E4 CMP ESI,08
XXXX:004013E7 JNZ 004013CC
Exemple: EDX=5, alors
X0 X1 X2 X3 X4 X5 X6 X7 ==[devient]==> X3 X4 X5 X6 X7 X0 X1 X2
On poursuit:
XXXX:004013F5 PUSH ECX ;BOUCLE #2 (ecx contient l'indice de boucle)
XXXX:004013F6 XOR EDX,EDX
XXXX:004013F8 XOR EAX,EAX
XXXX:004013FA MOV DL,[ECX+0040449F] ;lit S0, S1, ..., S7
XXXX:00401400 SUB AX,DX
XXXX:00401403 ADD AX,012C
XXXX:00401407 MOV BL,0A
XXXX:00401409 CWD
XXXX:0040190B IDIV BX
XXXX:0040140E MOV AL,[ECX+004044E2] ;lit X0, X1, ..., X7 (mis dans le DESORDRE)
XXXX:00401414 AND AL,0F
XXXX:00401416 ADD AL,0A
XXXX:00401418 SUB AL,DL
XXXX:0040141A CMP AL,09
XXXX:0040141C JBE 00401420
XXXX:0040141E SUB AL,0A
XXXX:00401420 OR AL,30
XXXX:00401422 MOV [ECX+004046E3],AL :on va encore obtenir 8 chiffres...
XXXX:00401428 POP ECX ;notons le T0, T1, ..., T7
XXXX:00401429 INC ECX
XXXX:0040142A CMP ECX,08
XXXX:0040142D JNZ 004013F5
La boucle suivante est exactement la mΩme que la BOUCLE #1 sauf que, Θvidemment les arguments ne
sont pas les mΩme!
XXXX:00401439 PUSH ECX
XXXX:0040143A MOV AL,[ECX+004044E2] ;lit X0, X1, ..., X7 (mis dans le DESORDRE)
XXXX:00401440 MOV DL,[ECX+004046E3] ;lit T0, T1, ..., T7
XXXX:00401446 SUB AX,DX
XXXX:00401449 MOV DL,[ECX+00404AF4] ;lit X7, X9, ..., Xe
...
exactement pareil que la BOUCLE #1
...
XXXX:00401463 MOV [ECX+004044E2],DL ;on va encore obtenir 8 chiffres...
XXXX:00401469 INC ECX ;notons le U0, U1, ..., U7
XXXX:0040146A CMP ECX,08
on continue...
... ;quelques lignes qui ne servent α rien...
XXXX:00401498 MOV DL,[004044E2] ;lit U0
XXXX:0040149E AND DL,0F
XXXX:004014A1 ADD ESI,EDX ;mΩme principe que tout α l'heure
XXXX:004014A3 XOR EDX,EDX
XXXX:004014A5 MOV EAX,ESI ;rΘutilise le ckecksum de la boucle prΘcΘdente
XXXX:004014A7 MOV CL,08
XXXX:004014A9 CWD
XXXX:004014AB IDIV CX ;edx: reste de la division euclidienne
XXXX:004014AE XOR ESI,ESI
Encore une fois le reste de la division va nous servir...
XXXX:004014B2 MOV AL,[ESI+004044E2] ;lit U0, U1, ..., U7
XXXX:004014B8 MOV [EDX+004046E3],AL ;recopie (dans le dΘsordre)
XXXX:004014BE INC EDX ;(c'est la mΩme chose qui ci-dessus)
XXXX:004014BF CMP EDX,08
XXXX:004014C2 JNZ 004014C9
XXXX:004014C4 MOV EDX,00000000
XXXX:004014C9 INC ESI
XXXX:004014CA CMP ESI,08
XXXX:004014CD JNZ 004014B2
Courage c'est la derniΦre boucle:
XXXX:004014DB PUSH ECX ;exactement pareil que la BOUCLE #2
...
XXXX:004014E0 MOV DL,[ECX+00404AF4] ;lit X7, X9, ..., Xe
...
XXXX:004014F4 MOV AL,[ECX+004046E3] ;lit U0, U1, ..., U7 ( mis dans le dΘsordre)
...
XXXX:00401508 MOV [ECX+004044E2],AL ;nos 8 chiffres finaux (*)
XXXX:0040150E POP ECX
XXXX:0040150F INC ECX ;boucle suivante
XXXX:00401510 CMP ECX,08
XXXX:00401513 JNZ 004014DB
(*) Ce nombre (= 8 chiffres) est ensuite comparΘ α 11111111.
Retrouvons maintenant un bon serial... Heureusement pour nous, chaque caractΦre est indΘpendant
les uns des autres.
Voilα ce qu'il faut trouver pour le 1er caractΦre:
L1: { ( (X0 - N0 - X7 +12C ) mod Ah ) OR 30h = S0
L2: { ( ( (X0' AND F) + Ah ) - ( (-S0 + 12C) mod Ah ) ) OR 30h = T0 (**)
L3: { ( (X0' - T0 - X7 + 12C) mod A ) OR 30h = U0
L4: { ( ( (U0' AND F) + Ah ) - ( (-X7 + 12C) mod Ah ) ) OR 30h = 31h (***)
Remarque: J'ai notΘ X0' l'octet X0 aprΦs mise en dΘsordre, mΩme chose pour U0'
(voir XXXX:004014AB et XXXX:004013C5).
(**): N'oublions pas que si T0>39h alors T0=T0-Ah ;mΩme chose pour (***).
Analysons la quatriΦme ligne (L4):
on doit avoir ((U0' AND F) + Ah) - ((-X7 + 12C) mod Ah) = 1. En n'oubliant pas la condition
(**), on a six possibilitΘs:
(U0' AND F) + Ah) = Fh et ((-X7 + 12C) mod Ah) = 4
ou (U0' AND F) + Ah) = Eh et ((-X7 + 12C) mod Ah) = 3
ou (U0' AND F) + Ah) = Dh et ((-X7 + 12C) mod Ah) = 2
ou (U0' AND F) + Ah) = Ch et ((-X7 + 12C) mod Ah) = 1
ou (U0' AND F) + Ah) = Bh et ((-X7 + 12C) mod Ah) = 0
ou (U0' AND F) + Ah) = Ah et ((-X7 + 12C) mod Ah) = 9
Et donc:
(U0' AND F) + Ah = {Fh, Eh, Dh, Ch, Bh ,Ah}
<=> (U0' AND F) = {5, 4, 3, 2, 1, 0}
<=> U0' = {35h, 34h, 33h, 32h, 31h, 30h}
Les caractΦres U0, U1, ..., U7 sont obligatoirement compris entre 30h et 35h.
On utilise la mΩme dΘmarche pour la ligne 2 (L2).
S0, S1, ..., S7 peut contenir les caractΦres suivants: {"0", "1", "2", "3", "8", "9", ":", ";", "<", "="}.
Mais en regardant la ligne 1 (L1), on voit que S0, S1, ..., S7 est issu d'un modulo Ah, ainsi,
les caractΦres de S0, S1, ..., S7 doivent obligatoirement Ωtre: {"0", "1", "2", "3", "8", "9"}
Grace α ces quelques restrictions on va pouvoir essayer de contruire des couples (X0-X7, ..., X7-Xe).
Voir ma source en C, ainsi pour chacun des huit lettres du nom, on va trouver des couples.
Remarque: Le caractΦre 8 est important car il est utilisΘ deux fois (couple X0-X7 et X7-Xe),
donc faut faire attention. Les 6 autres couples, je les ai pris un peu au hasard.
exemple: _123456_789abc_
(attention les deux couples X0-X7 et X7-Xe ont un terme commun!)
Que donne ma source?
Elle gΘnΦre les couples possibles pour chaque lettre et en prenant 8 couples τa peut marcher!
Pourquoi τa peut: parce que ma source suppose qu'il n'y a pas de mise en dΘsordre; X?=X?' et U?=U?'.
(voir en XXXX:004014AB et XXXX:004013C5). C'est selon moi la maniΦre la plus simple d'enregister ce crackme.
Et donc, il va falloir trouver les couples qui donnent bien EDX=0 (d'autres valeurs pour edx sont possibles) en
XXXX:004013CC et XXXX:004014B8. Afin de ne pas changer l'ordre de X0, X1, ..., X7
(mΩme chose pour U0, U1, ..., U7).
Comment trouver un bon serial?
Il faut dΘjα passer la premiΦre mise en dΘsordre, pour celα, un petit peu de bon sens; on
essaye de crΘer les 8 premiers caractΦres cycliques (exemple: 48484848), ou avec beaucoup de caractΦres
identiques. AprΦs quand on a passΘ la premiΦre mise en dΘsordre on fait des essais en changeant uniquement
les 7 derniers caractΦres afin de passer la deuxiΦme barriΦre (edx=0 en XXXX:004014AB; ou edx=? du moment que
U0=U0', ..., U7=U7').
Pour moi, je prend donc huit couples:
0 2 ;couple pour la lettre "L"
0 X ;couple pour la lettre "u"
0 8 ;couple pour la lettre "c"
4 8 ;couple pour la lettre "i"
1 8 ;couple pour la lettre "f"
0 9 ;couple pour la lettre "e"
4 X ;couple pour la lettre "r"
e n ;couple pour la lettre "4"
-----------------
0004104e2X8889Xn
A cela, s'ajoute un seiziΦme caractΦre qui n'est pas utilisΘ par la protection, et on obtient,
quelques bons serials (Name/ Lucifer48):
0004104e2X8889n*
0004104e2X8889d*
0004104e2X8889Z*
0004104e2X8889P*
0004104e2X8889F*
`004104e2X8889x*
...
`004104e2X8889F*
* constitue n'importe quel caractΦre
Status: registered!!
Battle Two: The Tower
XXXX:00401834 PUSH 004046E3 ;adresse du buffer
XXXX:00401839 PUSH EAX ;longueur du serial -1 (voir remarque)
XXXX:0040183A PUSH 0D ;WM_GETTEXT
XXXX:0040183C PUSH 000000CB ;serial edit box
XXXX:00401841 PUSH DWORD PTR [EBP+08] ;handle de la dialog box
XXXX:00401844 CALL USER32!SendDlgItemMessageA
XXXX:00401849 CALL 0040168B ;α explorer!
XXXX:0040184E CMP BYTEP PTR [004044E0],01
XXXX:00401855 JNZ 0040187D ;jmp = mauvais serial
Remarque: Le dernier caractΦre tapΘ au clavier n'est pas lu, car le buffer Θtant de taille EAX
(EAX Θtant la taille du serial obtenu via WM_GETTEXTLENGTH juste avant); en fait la taille du buffer
est EAX-1; le dernier octet Θtant le caractΦre nul; donc en doit rajouter un caractΦre quelconque
aprΦs le serial pour obtenir le bonne longueur. A mon avis, c'est volontaire car le nom est lu
dans son intΘgralitΘ (XXXX:00401806 INC EAX).
Notons X0, X1, ..., X9 les caractΦres du serials; et N0, N1, ..., N8 ceux du nom.
Dans le call 0040168B:
... (eax=ebx=ecx=edx=0)
XXXX:00401693 MOV AL,[004046E3] ;X0
XXXX:00401698 XOR AL,[004046EC] ;X9
XXXX:0040169E XOR AH,AL ;AL=AH
XXXX:004016A0 XOR AX,[004046E4] ;X2 X1
XXXX:004016A7 XOR EAX,[004046E6] ;X6 X5 X4 X3
XXXX:004016AD XOR EAX,[004046E8] ;X8 X7 X6 X5
XXXX:004016B3 XOR EAX,[00404AE5] ;N3 N2 N1 N0
XXXX:004016B9 XOR EAX,[00404AE8] ;N6 N5 N4 N3
XXXX:004016BF XOR AX,[00404AEC] ;N8 N7
XXXX:004016C6 MOV ECX,EAX ;garde le rΘsultat pour plus tard
XXXX:004016C8 MOV EBX,00000029
XXXX:004016CD CWD
XXXX:004016CF IDIV EBX
XXXX:004016D1 MOV EAX,EDX
XXXX:004016D3 MOV EBX,00000009
XXXX:004016D8 CWD
XXXX:004016DA IDIV EBX
XXXX:004016DC MOV EAX,EDX
Donc EAX= (EAX mod 41d) mod 9; on a 9 possibilitΘs:
EAX=0: EAX = (ECX mod 7) + 1 et ECX = ECX XOR 00BC614E (BC614Eh=12345678d)
EAX=1: ECX = ECX XOR 0023CACE ;23CACEh = 2345678d
EAX=2: ECX = ECX XOR 0005464E ; 5464Eh = 345678d
EAX=3: ECX = ECX XOR 0000B26E ; B26Eh = 45678d
EAX=4: ECX = ECX XOR 0000162E ; 162Eh = 5678d
EAX=5: ECX = ECX XOR 000002A6 ; 2A6h = 678d
EAX=6: ECX = ECX XOR 0000004E ; 4Eh = 78d
EAX=7: ECX = ECX XOR 00000008 ; 8h = 8d
EAX=8: ECX = ECX XOR 00000000
Si le nom n'est pas assez grand, on peut facilement utiliser le fait que l'octet
est nul (le buffer est largement assez grand).
XXXX:00401743 CMP EAX,36F95001
XXXX:00401749 SETZ AL
XXXX:0040174C MOV [004044E0],AL
XXXX:00401751 RET
-
On suppose que le rΘsultat du double modulo est: 8
alors en XXXX:004016C6, on doit trouver: 36F95001
mais (36F95001h mod 41d) mod 9 = 2
cette possibilitΘ est donc impossible; elle n'est donc jamais empreintΘe.
-
On suppose que le rΘsultat du boucle modulo est: 7
alors en XXXX:004016C6, on doit avoir: 36F95001 XOR 8 = 36F95009
mais (36F95009h mod 41d) mod 9 = 5
-
On suppose que le rΘsultat du boucle modulo est: 6
alors en XXXX:004016C6, on doit avoir: 36F95001 XOR 4E = 36F9504F
mais (36F9504Fh mod 41d) mod 9 = 7
-
On suppose que le rΘsultat du boucle modulo est: 5
alors en XXXX:004016C6, on doit avoir: 36F95001 XOR 2A6 = 36F952A7
mais (36F952A7h mod 41d) mod 9 = 1
-
On suppose que le rΘsultat du boucle modulo est: 4
alors en XXXX:004016C6, on doit avoir: 36F95001 XOR 162E = 36F9462F
mais (36F9462Fh mod 41d) mod 9 = 7
-
On suppose que le rΘsultat du boucle modulo est: 3
alors en XXXX:004016C6, on doit avoir: 36F95001 XOR B26E = 36F9E26F
mais (36F9E26Fh mod 41d) mod 9 = 0
-
On suppose que le rΘsultat du boucle modulo est: 2
alors en XXXX:004016C6, on doit avoir: 36F95001 XOR 5464E = 36FC164F
mais (36FC164Fh mod 41d) mod 9 = 0
-
On suppose que le rΘsultat du boucle modulo est: 1
alors en XXXX:004016C6, on doit avoir: 36F95001 XOR 23CACE = 36DA9ACF
mais (36DA9ACFh mod 41d) mod 9 = 7
Tout τa pour dire qu'en XXXX:004016C6, ecx mod 41d = { 36d, 27d, 18d, 9d, 0d }.
On exΘcute le cas ou EAX=0, pour obtenir une nouvelle valeur (entre 1 et 8) de EAX.
En va recommencer la mΩme dΘmarche que ci-dessus, aprΦs avoir exΘcutΘ la close EAX=0.
RΘsultat α trouver: 36F95001 XOR 00BC614E = 3645314F
Mais avant de trouver 3645314F, n'oublions pas qu'on doit avant passer de le test du boucle modulo
(en ayant un reste nul). On voit, qu'il y a deux candidats (reste 3 et 2; voir ci-dessus).
Donc:
-
On suppose que le rΘsultat du double modulo est: 3
alors en XXXX:004016FD, on doit trouver: 3645314F XOR B26E = 36458321
mais (36458321h mod 7) + 1 = 1
τa ne va pas!
-
On suppose que le rΘsultat du double modulo est: 2
alors en XXXX:004016FD, on doit trouver: 3645314F XOR 5464E = 36407701
mais (36407701h mod 7) + 1 = 2 (OUI!!!)
Je rΘcapitule:
- En XXXX:004016C6 j'ai ECX = 36407701
- (36407701h mod 41d) mod 9 = 0 (en eax)
- 36407701 XOR 00BC614E = 36FC164F (XXXX:004016FD)
- (36407701h mod 7) + 1 = 2
- J'ai ECX = 36FC164F (et EAX=2)
- 36FC164F XOR 5464Eh = 36F95001 (= bon rΘsultat α trouver!!)
Ansi l'unique dword possible (en XXXX:004016C6) est: 36407701.
Ce qui suit est ultra-classique (prΘsent dans pas mal de crackme).
J'enlΦve en premier le masque de mon nom ( 6963754Ch XOR 72656669h XOR 00003834 = 1B062B11 ).
36407701 XOR 1B062B11 = 2D465C10
Et donc il reste α rΘsoudre celα:
00 00 X0 X0
xor 00 00 X9 X9
xor 00 00 X2 X1
xor X6 X5 X4 X3
xor X8 X7 X6 X5
-----------
2D 46 5C 10
Je prend par exemple (j'essaye de prendre au plus simple):
X1=X9=X0= 30h ("0")
X3= 50h ("P")
X5= 70h ("p")
X4= 2Dh ("-")
X6= 41h ("A")
X2= 30h ("0")
X5 XOR 46 = X7 donc X7= 36h ("6")
X6 XOR 2D = X8 donc X8= 6Ch ("l")
En mettant dans l'ordre, on obtient le serial: 000P-pA6l0
A ceci s'ajoute la remarque du dΘbut du chapitre; ce qui nous donne un serial:
Name/ Lucifer48
Serial/ 000P-pA6l0*
(* est un caractΦre quelconque)
ou mieux:
Serial/ #00P-pA6l#*
(* est un caractΦre quelconque; # est un caractΦre quelconque aussi)
Il y a bien d'autres possibilitΘs...
Status: registered!!
The Final Battle: The Princess
XXXX:0040270D CMP BYTE PTR [004044E1],01 ;bonne combinaison des buttons ?
XXXX:00402714 JNZ 00402748
XXXX:00402716 PUSH 00 ;MB_OK
XXXX:00402718 PUSH 0040446D ;You have succeeded!
XXXX:0040271D PUSH 004043D6 ;message de fin
XXXX:00402722 PUSH DWORD PTR [EBP+08] ;handle
XXXX:00402725 CALL USER32!MessageBoxA
XXXX:0040272A PUSH FF
XXXX:0040272C PUSH DWORD PTR [EBP+08]
XXXX:0040272F CALL USER32!EndDialog
XXXX:00402734 JMP 00402748
Si on a bien disposΘ les check box alors [004044E1] est mis α 1 (juste avant il y une vΘrifivation,
si on a bien mis quelque chose dans l'edit box) et lα, une dialog box se crΘe et on se retrouve
devant la princesse. Super !!!
La combinaison la plus simple est d'appuyer sur 1 seul boutton:
O O O O
O o o O
O ___ O
O X <------ cette check box
O O O O
XXXX:004011F8 CALL USER32!DialogBoxParamA ;dialog box du crackme
XXXX:004011FD CMP BYTE PTR [004044E1],01 ;voir commentaire ci-dessous
XXXX:00401204 JNZ 00401221
XXXX:00401206 MOV EAX,004018B5
...
XXXX:00401216 PUSH DWORD PTR [004044D4]
XXXX:0040121C CALL USER32!DialogBoxParamA ;affiche la princesse
XXXX:00401221 JMP 004012D8
En fait pour arriver α la MessageBox, il y a un patch α faire:
XXXX:004026C7 CMP AX,013F ;control ID du boutton "OK"
XXXX:004026CB JNZ 0040274A
XXXX:004026CD SHR EAX,10 ;EAX=00000000
XXXX:004026D0 OR AX,AX
XXXX:004026D3 JNZ 00402781 ;ZF est armΘ (no jump)
XXXX:004026D9 CMP EAX,-01 ;c'est IMPOSSIBLE!!!
XXXX:004026DC JNZ 00402736
C'Θtait pour τa l'allusion: je vois l'ΘpΘe mais pas la lame ???
Conclusion & Greetings
Finalement j'ai rΘussi ! La bataille 1 Θtait vraiment la plus dure. La bataille 2 Θtait, disons
classique; quand α la bataille 3: un peu bizarre ! C'Θtait quand mΩme plus dure que ConquerMe I.
En attendant (peut-Ωtre) ConquerMe III (codΘ en assembleur bien s√r...); je vous salue!
Greetings: All ID members (Volatility, Torn@do, ...), Eternal Bliss, ACiD BuRN, LaZaRuS,
Duelist, people on #cracking4newbies, ..., and YOU MisterE for creating two excellent crackmes !!!
et toi petit cracker franτais, mon ami, mon frΦre, qui lit ces quelques lignes...
(c) Lucifer48. All rights reversed